/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package exatrez.manager;

import com.google.inject.Inject;
import com.wideplay.warp.persist.Transactional;
import exatrez.dao.DocumentDAO;
import exatrez.dao.FolderDAO;
import exatrez.dao.ObservationDAO;
import exatrez.dao.ObservationHistoryTaskDAO;
import exatrez.dao.ObservationSummaryDAO;
import exatrez.dao.ObservationTaskDAO;
import exatrez.model.Document;
import exatrez.model.Folder;
import exatrez.model.Observation;
import exatrez.model.ObservationHistoryTask;
import exatrez.model.ObservationSummary;
import exatrez.model.ObservationTask;
import exatrez.model.User;
import exatrez.model.UserGroup;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 *
 * @author fikri
 */
public class ObservationManager {
    
    @Inject private ObservationDAO observatioDAO;
    @Inject private ObservationSummaryDAO observationSummaryDAO;
    @Inject private ObservationTaskDAO observationTaskDAO;
    @Inject private DocumentDAO documentDAO;
    @Inject private FolderDAO folderDAO;
    
    @Inject private SequenceManager sequence;
    @Inject private ObservationHistoryTaskDAO historyDAO;
    @Inject
    exatrez.stripes.ObservationConfiguration obsConf;
    
     @Inject
    protected com.google.inject.Provider<Session> sessionProvider;
     
    private static Logger LOG = LoggerFactory.getLogger(ObservationManager.class);
    
    @Transactional
    public Observation saveOrUpdate(Observation observation) {
       
        return observatioDAO.saveOrUpdate(observation);
    }
    
    @Transactional
    public List<ObservationSummary> saveOrUpdateSummary(List<ObservationSummary> list) {
        List<ObservationSummary> lists = new ArrayList<ObservationSummary>();
        for (ObservationSummary sum : list) {
            lists.add (observationSummaryDAO.saveOrUpdate(sum));
        }
        return lists;
    }
    
    public ObservationSummary findSummary(Integer id) {
        return observationSummaryDAO.findById(id);
    }
    
    @Transactional
    public void saveTask(ObservationTask task) {
       observationTaskDAO.save(task);
    }
    
    @Transactional
    public void saveOrUpdateTask(ObservationTask task) {
       observationTaskDAO.saveOrUpdate(task);
    }
    
    @Transactional
    public void saveOrUpdateTask(List<ObservationTask> tasks) {
        for (ObservationTask task : tasks) {
           observationTaskDAO.saveOrUpdate(task);
        }
    }
    
    public List<Observation> findAll(Observation obs) {
        StringBuilder sb = new StringBuilder("select p from Observation p");
        if (obs != null) {
            sb.append(" where p.vessel.vesselId = :id");
        }
        
        Session session = sessionProvider.get();
        
        Query query = session.createQuery(sb.toString());
        
        if (obs !=null) {
            query.setParameter("id", obs.getVessel().getVesselId());
        }
        
        return query.list();
                
    }
    
    public List<Observation> findObsClose(Observation obs) {
        StringBuilder sb = new StringBuilder("select p from Observation p where p.status.statusRemarkName in('PENDING','OPEN')");
        if (obs != null) {
            sb.append(" and p.vessel.vesselId = :id");
        }
        
        Session session = sessionProvider.get();
        
        Query query = session.createQuery(sb.toString());
        
        if (obs !=null) {
            query.setParameter("id", obs.getVessel().getVesselId());
        }
        
        return query.list();
                
    }
    
    @Transactional
    public void saveOrUpdateTaskWithHistory(List<ObservationTask> tasks, List<ObservationHistoryTask> histories) {
        for (ObservationTask task : tasks) {
           observationTaskDAO.saveOrUpdate(task);
        }
        
        for(ObservationHistoryTask history : histories) {
            historyDAO.saveOrUpdate(history);
        }
    }
    
    
    @Transactional
    public void saveOrUpdateTaskWithDocuments(ObservationTask task) {
       observationTaskDAO.saveOrUpdate(task);
    }
    
    @Transactional
    public void deleteTask(ObservationTask task) {
       observationTaskDAO.delete(task);
    }
    
    @Transactional
    public void deleteDocument(Document document) {
       documentDAO.delete(document);
    }
    
    @Transactional
    public void saveOrUpdateDocument(Document document) {
        documentDAO.saveOrUpdate(document);
    }
    
    
    @Transactional
    public void saveOrUpdateDocument(List<Document> documents) {
        for (Document document : documents) {
            documentDAO.saveOrUpdate(document);
        }
    }
    
    @Transactional
    public void saveOrUpdateFolder(Folder folder) {
        folderDAO.saveOrUpdate(folder);
    }
    
    public List<Observation> getDraftList(Observation observation, User user) {
        StringBuilder sb = new StringBuilder("select p from Observation p ")
                .append("where dateSubmit is null ");
//        append("and infoAudit.createId.userId = :userId ");
        
        Session session = sessionProvider.get();
        
        if (observation!=null && observation.getVessel()!=null) {
            sb.append("and vessel.vesselId = :vesselId ");
        }
        
        if (observation!=null && observation.getDateOfInspection()!=null) {
            sb.append("and dateOfInspection = :date ");
        }
        Query query = session.createQuery(sb.toString());
        
        if (observation!=null && observation.getVessel()!=null) {
            query.setParameter("vesselId", observation.getVessel().getVesselId());
        }
        
        if (observation!=null &&  observation.getDateOfInspection()!=null) {
            query.setParameter("date", observation.getDateOfInspection());
        }
        
        return query.list();
    }
    
    public List<Observation> getListReport(Observation observation, User user) {
        StringBuilder sb = new StringBuilder("select p from Observation p ")
                .append("where dateSubmit is not null ")
                .append("and status.statusRemarkCodeId not in (:code) ");
//        append("and infoAudit.createId.userId = :userId ");
        
        Session session = sessionProvider.get();
        
        if (observation!=null && observation.getVessel()!=null) {
            sb.append("and vessel.vesselId = :vesselId ");
        }
        
        if (observation!=null && observation.getDateOfInspection()!=null) {
            sb.append("and dateOfInspection = :date ");
        }
        Query query = session.createQuery(sb.toString()).setParameter("code", 1);
        
        if (observation!=null && observation.getVessel()!=null) {
            query.setParameter("vesselId", observation.getVessel().getVesselId());
        }
        
        if (observation!=null &&  observation.getDateOfInspection()!=null) {
            query.setParameter("date", observation.getDateOfInspection());
        }
        
        return query.list();
    }
    
    public List<Observation> getCloseReport(Observation observation, User user, String year) {
        StringBuilder sb = new StringBuilder("select p from Observation p ")
                .append("where dateSubmit is not null ")
                .append("and status.statusRemarkCodeId = :code ");
//        append("and infoAudit.createId.userId = :userId ");
        
        Session session = sessionProvider.get();
        
        if (observation!=null && observation.getVessel()!=null) {
            sb.append("and vessel.vesselId = :vesselId ");
        }
        
        if ( StringUtils.isNotBlank(year)) {
            sb.append("and year(dateOfInspection) = :year ");
        }
        Query query = session.createQuery(sb.toString()).setParameter("code", 1);
        
        if (observation!=null && observation.getVessel()!=null) {
            query.setParameter("vesselId", observation.getVessel().getVesselId());
        }
        
        if (StringUtils.isNotBlank(year)) {
            query.setString("year", year);
        }
        
        return query.list();
    }
    
    public List<Observation> getSuperintendenceListReport(Observation observation, User user) {
        String groupId = user.getRoles().get(0).getGroup().getGroupId().toString();
        String flagEdit = user.getRoles().get(0).getObsFlag();
        List<Observation> list;// = new ArrayList<Observation>();
//        LOG.debug("User :"+user.getUserId()+", Group :"+groupId+", flagEdit :"+flagEdit);
        if((groupId.equals(obsConf.getProperty("group.crew")) || groupId.equals(obsConf.getProperty("group.procurement")) || 
                groupId.equals(obsConf.getProperty("group.hsse")) || groupId.equals(obsConf.getProperty("group.ism"))) && flagEdit.equals("T")){
//            LOG.debug("<getSuperintendenceListReport>  cluster IF");
            list = this.getSuperintendenceListReport(observation, user, false);
        }else{
//            LOG.debug("<getSuperintendenceListReport>  cluster ELSE");
            list = this.getSuperintendenceListReport(observation, user, true);
        }
//        LOG.debug("<getSuperintendenceListReport> list.size :"+list.size());
        return list;
    }
    
    public List<Observation> getSuperintendenceListReport(Observation observation, User user, boolean isSuper) {
        StringBuilder sb = new StringBuilder("select p from Observation p ")
                .append("where dateSubmit is not null ")
                .append("and status.statusRemarkCodeId not in (:code) ");
        
        Session session = sessionProvider.get();
        
        if (observation!=null && observation.getVessel()!=null) {
            sb.append("and vessel.vesselId = :vesselId ");
        }
        
        if(isSuper){
            sb.append("and assignee.userId = :userId ");
        }
        
        if (observation!=null && observation.getDateOfInspection()!=null) {
            sb.append("and dateOfInspection = :date ");
        }
        Query query = session.createQuery(sb.toString()).setParameter("code", 1);
        
        if(isSuper){
            query.setParameter("userId", user.getUserId());
        }
        
        if (observation!=null && observation.getVessel()!=null) {
            query.setParameter("vesselId", observation.getVessel().getVesselId());
        }
        
        if (observation!=null &&  observation.getDateOfInspection()!=null) {
            query.setParameter("date", observation.getDateOfInspection());
        }
        
        return query.list();
    }
    
    public ObservationHistoryTask getLatestHistory(String obsTaskId) {
        StringBuilder sb = new StringBuilder("select p from ObservationHistoryTask p ")
                .append("where observationTask.observationTaskId = :id order by obsHistoryTask desc");
        
        Session session = sessionProvider.get();
        Query query = session.createQuery(sb.toString()).setParameter("id", obsTaskId);
        
        if (!query.list().isEmpty()) return (ObservationHistoryTask)query.list().get(0);
        else return null;
    }
 
    // !hack from admin    
     public List<Observation> findAllVesselId(String vesselId) {
        String query = "SELECT a FROM Observation a WHERE a.vessel.vesselId = :vesselId";
        Query q = sessionProvider.get().createQuery(query).setString("vesselId", vesselId);
        return q.list();
    }
     
     public String getSeverityDay(String severityId) {
         String result = "0";
         String query = "SELECT a.severityDay FROM SeverityCode a WHERE a.severityCodeId = :id";
         Query q = sessionProvider.get().createQuery(query).setString("id", severityId);
         Object obj = q.uniqueResult();
         if (obj!=null) {
             result = String.valueOf(obj);
         }
         return result;
     }
     
     public void updateTasks(String oldID, String id) {
         Session session = sessionProvider.get();        
         
         Query q = 
                 session.createQuery("UPDATE ObservationTask m SET "
                 + "m.observationTaskId = :id WHERE m.observationTaskId = :id2")
                 .setParameter("id", id).setParameter("id2", oldID);
         
         q.executeUpdate();
         
         
     }
    
    
    public Observation getObservation(String id) {
        return observatioDAO.findById(Integer.valueOf(id));

    }
    
    public ObservationTask getObservationTask(String id) {
        return observationTaskDAO.findById(id);

    }
    
    public String getSequence(String vesselAbbr) {
        SimpleDateFormat sdf = new SimpleDateFormat("yy");
        String year = sdf.format(new Date());
        String seq = sequence.getSequence(vesselAbbr);       
        return new StringBuilder(vesselAbbr)
                .append("-")
                .append(year)
                .append("-")
                .append(seq)
                .toString();        
    }
    
    public String getSequenceID(String vesselAbbr) {
        SimpleDateFormat sdf = new SimpleDateFormat("yy");
        String year = sdf.format(new Date());
        return new StringBuilder(vesselAbbr)
                .append("-")
                .append(year)
                .append("-")
                .toString();
    }
    
    public String[] getMaEmail(String userId) {
        
        StringBuilder sb = new StringBuilder("select p from UserGroup p ")
                .append("where p.group.groupId = :group and p.user.userId not in (:id) and p.user.userId != 'abu.audit' ");
        Session session = sessionProvider.get();
        Query query = session.createQuery(sb.toString()).setInteger("group", 1).setParameter("id", userId);
        if (!query.list().isEmpty()) {
            String[] emails = new String[query.list().size()];
            List<UserGroup> userGroups = query.list();
            for (int i=0; i<userGroups.size();i++) {
                UserGroup ug = userGroups.get(i);
                if (ug.getUser() != null) {
                    emails[i] = ug.getUser().getEmail();
                }
            }
            return emails;
        }
        return null;
    }
    
    public List<Map<String, String>> getTasks(String userId) {
        
        Calendar cal = Calendar.getInstance();        
        SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");

        List<Map<String, String>> list = new ArrayList<Map<String, String>>();        

        try {
            Session session = sessionProvider.get();
            
            Query query = session.createQuery("Select p from Inbox p "
                    + "where p.infoAudit.createId.userId = :userId and date(p.infoAudit.createDate) = :date "
                    + "and p.status.inboxStsCodeId = :sts");
            query.setParameter("userId", userId);
            query.setParameter("date", cal.getTime());
            query.setParameter("sts", 1);
            
            if (!query.list().isEmpty()) return null;            
            
            query = session.createQuery("Select count(distinct p.observationTask.observationTaskId) as count, "
                    + "p.observationTask.observation.observationId "
                    + "from ObservationHistoryTask p where date(p.responseDate) = :date "
                    + "group by p.observationTask.observation.observationId");
            query.setParameter("date", cal.getTime());
            LOG.debug("size {}", query.list().size());
            List<Object[]> listOfObj = query.list();            
                
            for (Object[] obj : listOfObj) {                
                LOG.debug("obj {}", obj[0].toString());
                LOG.debug("obj {}", obj[1].toString());
                
                
                Map<String, String> map = new HashMap<String, String>();
                
                String responseUptodate = obj[0].toString();
                String observationId = obj[1].toString();
                if (StringUtils.isNotBlank(observationId)) {
                    query = session.createQuery("select p from ObservationTask p "
                            + "where p.observation.observationId = :id");
                    query.setParameter("id", Integer.parseInt(observationId));
                    List<ObservationTask> tasks = query.list();
                    if (!tasks.isEmpty()) {
                       int totalObs = tasks.size();
                       ObservationTask task = tasks.get(0);
//                       Observation obs = task.getObservation();
                       List<Object[]> listOfObj2 = session.createQuery("select p.infoAudit.createId.userId, "
                               + "p.assignee.userId, p.infoAudit.createId.email, p.vessel.vesselName, date(p.dateOfInspection) "
                               + "from Observation p "
                               + "where p.observationId = :id")
                               .setParameter("id", Integer.parseInt(observationId))
                               .list();
                       Object[] ob = listOfObj2.get(0);                                        
                       String vessel = ob[3].toString(); 
                       Date dateInspection = (Date)ob[4]; 
                       map.put("vessel", vessel);
                       map.put("dateInspection", sdf.format(dateInspection));
                       map.put("totalObs", String.valueOf(totalObs));
                       map.put("responseToDate", responseUptodate);
                       list.add(map);
                    }                    
                }
            }

        } catch (HibernateException ex) {
            LOG.error(null, ex);
        } 
        return list;
    }
    
}
